import pandas as pd
import matplotlib.pyplot as plt
import os
import glob
import numpy as np
import re
from pathlib import Path


def read_excel_config(excel_path):
    """
    读取Excel配置文件，获取不同xnode-yproc对应的O和L值
    返回格式: {'1node-2proc': {'o': value, 'l': value}, ...}
    """
    try:
        df = pd.read_excel(excel_path)
        config_map = {}
        
        # 假设Excel文件有列: config, o, l
        # 根据实际Excel文件结构调整列名
        for _, row in df.iterrows():
            config_key = row['config']  # 例如: '1node-2proc'
            config_map[config_key] = {
                'o': row['o'],
                'l': row['l']
            }
        
        return config_map
    except Exception as e:
        print(f"读取Excel配置文件时出错: {e}")
        return {}


def extract_node_proc_from_filename(filename):
    """
    从文件名中提取xnode和yproc信息
    支持格式: xnode-yproc-cnxxxx-xiteration-zzzz 或 xnode-yproc-cn[xxx-xxx]-xiteration-zzz
    """
    # 匹配模式: 数字+node-数字+proc
    pattern = r'(\d+)node-(\d+)proc'
    match = re.search(pattern, filename)
    
    if match:
        x_node = int(match.group(1))
        y_proc = int(match.group(2))
        return x_node, y_proc, f"{x_node}node-{y_proc}proc"
    
    return None, None, None


def collect_csv_files(base_dir):
    """
    收集所有CSV文件并按xnode-yproc分组
    返回格式: {'1node-2proc': [file_paths], ...}
    """
    grouped_files = {}
    
    # 遍历所有子文件夹
    for subfolder in os.listdir(base_dir):
        subfolder_path = os.path.join(base_dir, subfolder)
        
        if not os.path.isdir(subfolder_path):
            continue
            
        # 检查子文件夹名称是否符合xnode格式
        if not re.match(r'\d+node', subfolder):
            continue
            
        print(f"处理子文件夹: {subfolder}")
        
        # 查找该子文件夹下的所有CSV文件
        csv_pattern = os.path.join(subfolder_path, "*.csv")
        csv_files = glob.glob(csv_pattern)
        
        for csv_file in csv_files:
            filename = os.path.basename(csv_file)
            x_node, y_proc, config_key = extract_node_proc_from_filename(filename)
            
            if config_key:
                if config_key not in grouped_files:
                    grouped_files[config_key] = []
                grouped_files[config_key].append(csv_file)
    
    return grouped_files


def process_csv_group_for_average(csv_files, config_key):
    """
    处理同一组的CSV文件，合并数据并计算平均值
    返回按total_size分组的平均avg_comm_time
    """
    all_data = []
    
    for csv_file in csv_files:
        try:
            df = pd.read_csv(csv_file)
            
            # 检查必要的列是否存在
            required_columns = ['comm_type', 'total_size', 'avg_comm_time']
            if not all(col in df.columns for col in required_columns):
                print(f"  文件 {csv_file} 缺少必要的列，跳过")
                continue
                
            # 添加文件来源信息
            df['source_file'] = os.path.basename(csv_file)
            all_data.append(df)
            
        except Exception as e:
            print(f"  读取文件 {csv_file} 时出错: {e}")
            continue
    
    if not all_data:
        print(f"  配置 {config_key}: 没有有效的CSV文件")
        return None
    
    # 合并所有数据
    combined_df = pd.concat(all_data, ignore_index=True)
    print(f"  配置 {config_key}: 合并后总数据量 {len(combined_df)} 条")
    
    # 筛选条件
    # 1. comm_type == 55 (尝试字符串和整数两种方式)
    filtered_df = combined_df[(combined_df['comm_type'] == 55) | (combined_df['comm_type'] == '55')]
    print(f"  步骤1筛选后(comm_type == 55 或 '55'): {len(filtered_df)} 条数据")
    
    # 2. total_size > 0 (可选筛选条件)
    filtered_df = filtered_df[filtered_df['total_size'] > 0]
    print(f"  步骤2筛选后(total_size > 0): {len(filtered_df)} 条数据")
    
    if filtered_df.empty:
        print(f"  配置 {config_key} 筛选后没有数据")
        return None
    
    # 按total_size分组并计算平均值
    avg_data = filtered_df.groupby('total_size')['avg_comm_time'].mean().reset_index()
    avg_data = avg_data.sort_values('total_size')
    
    print(f"  配置 {config_key}: 计算平均值后有 {len(avg_data)} 个数据点")
    return avg_data


def create_line_plot_for_all_configs(all_config_data, config_map, target_dir):
    """
    创建包含所有配置的折线图
    """
    plt.figure(figsize=(14, 10))
    
    # 定义颜色和标记样式
    colors = ['blue', 'red', 'green', 'orange', 'purple', 'brown', 'pink', 'gray', 'olive', 'cyan']
    markers = ['o', 's', '^', 'D', 'v', '<', '>', 'p', '*', 'h']
    
    color_idx = 0
    
    # 为每个配置绘制折线
    for config_key, data in all_config_data.items():
        if data is not None and not data.empty:
            color = colors[color_idx % len(colors)]
            marker = markers[color_idx % len(markers)]
            
            plt.plot(data['total_size'], data['avg_comm_time'], 
                    color=color, marker=marker, linewidth=2, markersize=6,
                    label=f'{config_key}', alpha=0.8)
            
            color_idx += 1
    
    # 设置图表属性
    plt.xlabel('Total Size (Bytes)', fontsize=14)
    plt.ylabel('Average Communication Time (μs)', fontsize=14)
    plt.title('Communication Time vs Total Size for Different Configurations\n(comm_type=55, total_size>20)', fontsize=16)
    plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', fontsize=10)
    plt.grid(True, alpha=0.3)
    
    # 设置对数坐标轴（如果数据范围很大）
    plt.xscale('log')
    plt.yscale('log')
    
    # 保存图片
    output_filename = "all_configs_line_plot.png"
    output_path = os.path.join(target_dir, output_filename)
    plt.savefig(output_path, dpi=300, bbox_inches='tight')
    plt.close()
    
    print(f"已保存综合折线图: {output_path}")


def create_individual_line_plots(all_config_data, config_map, target_dir):
    """
    为每个配置创建单独的折线图，并添加C-LoP模型线
    """
    individual_dir = os.path.join(target_dir, "individual_plots")
    os.makedirs(individual_dir, exist_ok=True)
    
    for config_key, data in all_config_data.items():
        if data is None or data.empty:
            continue
            
        plt.figure(figsize=(10, 8))
        
        # 绘制实际数据折线
        plt.plot(data['total_size'], data['avg_comm_time'], 
                'bo-', linewidth=2, markersize=6, label='Actual Data (Average)')
        
        # 获取配置参数并绘制C-LoP模型线
        # config_info = config_map.get(config_key)
        # if config_info:
        #     O = config_info['o']
        #     L = config_info['l']
            
        #     # 创建拟合直线
        #     x_min, x_max = data['total_size'].min(), data['total_size'].max()
        #     x_line = np.linspace(x_min, x_max, 100)
        #     y_line = O + L * x_line
            
        #     plt.plot(x_line, y_line, 'r-', linewidth=2, 
        #             label=f'C-LoP Model: y = {O:.6f} + {L:.6f}x')
        # else:
        #     print(f"未找到配置 {config_key} 的O和L参数")
        
        # 设置图表属性
        plt.xlabel('Total Size (Bytes)', fontsize=12)
        plt.ylabel('Average Communication Time (μs)', fontsize=12)
        plt.title(f'Communication Time vs Total Size\nConfiguration: {config_key}', fontsize=14)
        plt.legend()
        plt.grid(True, alpha=0.3)
        
        # 保存图片
        output_filename = f"{config_key}_line_plot.png"
        output_path = os.path.join(individual_dir, output_filename)
        plt.savefig(output_path, dpi=300, bbox_inches='tight')
        plt.close()
        
        print(f"已保存单独折线图: {output_filename}")


def create_comparison_by_node_count(all_config_data, target_dir):
    """
    按节点数量分组比较
    """
    # 按节点数分组
    node_groups = {}
    for config_key, data in all_config_data.items():
        if data is None or data.empty:
            continue
        
        # 提取节点数
        match = re.search(r'(\d+)node', config_key)
        if match:
            node_count = int(match.group(1))
            if node_count not in node_groups:
                node_groups[node_count] = {}
            node_groups[node_count][config_key] = data
    
    # 为每个节点数创建比较图
    for node_count, configs in node_groups.items():
        plt.figure(figsize=(12, 8))
        
        colors = ['blue', 'red', 'green', 'orange', 'purple', 'brown']
        color_idx = 0
        
        for config_key, data in configs.items():
            color = colors[color_idx % len(colors)]
            plt.plot(data['total_size'], data['avg_comm_time'], 
                    color=color, marker='o', linewidth=2, markersize=4,
                    label=config_key, alpha=0.8)
            color_idx += 1
        
        plt.xlabel('Total Size (Bytes)', fontsize=12)
        plt.ylabel('Average Communication Time (μs)', fontsize=12)
        plt.title(f'Communication Time Comparison for {node_count} Node Configurations', fontsize=14)
        plt.legend()
        plt.grid(True, alpha=0.3)
        plt.xscale('log')
        plt.yscale('log')
        
        # 保存图片
        output_filename = f"{node_count}node_comparison.png"
        output_path = os.path.join(target_dir, output_filename)
        plt.savefig(output_path, dpi=300, bbox_inches='tight')
        plt.close()
        
        print(f"已保存节点比较图: {output_filename}")


def create_summary_report(all_config_data, target_dir):
    """
    创建汇总报告
    """
    report_path = os.path.join(target_dir, "line_plot_analysis_summary.txt")
    
    with open(report_path, 'w', encoding='utf-8') as f:
        f.write("=== 折线图数据分析汇总报告 ===\n\n")
        f.write(f"总共处理 {len(all_config_data)} 个配置组:\n\n")
        
        for config_key, data in all_config_data.items():
            f.write(f"配置: {config_key}\n")
            if data is not None and not data.empty:
                f.write(f"  数据点数量: {len(data)}\n")
                f.write(f"  total_size范围: {data['total_size'].min()} - {data['total_size'].max()}\n")
                f.write(f"  avg_comm_time范围: {data['avg_comm_time'].min():.6f} - {data['avg_comm_time'].max():.6f}\n")
            else:
                f.write(f"  状态: 无有效数据\n")
            f.write("\n")
    
    print(f"已生成汇总报告: {report_path}")


def main(base_dir, target_dir, excel_path):
    """
    主函数
    """
    print("开始分析...")
    
    # 创建目标目录
    os.makedirs(target_dir, exist_ok=True)
    
    # 读取Excel配置
    print("读取Excel配置文件...")
    config_map = read_excel_config(excel_path)
    print(f"读取到 {len(config_map)} 个配置")
    
    # 收集并分组CSV文件
    print("收集CSV文件...")
    grouped_files = collect_csv_files(base_dir)
    print(f"发现 {len(grouped_files)} 个配置组")
    
    # 处理每个配置组，计算平均值
    all_config_data = {}
    for config_key, csv_files in grouped_files.items():
        print(f"\n处理配置组: {config_key}")
        
        # 处理CSV数据并计算平均值
        avg_data = process_csv_group_for_average(csv_files, config_key)
        all_config_data[config_key] = avg_data
    
    # 过滤掉没有数据的配置
    valid_configs = {k: v for k, v in all_config_data.items() if v is not None and not v.empty}
    print(f"\n有效配置数量: {len(valid_configs)}")
    
    # 创建综合折线图
    print("\n创建综合折线图...")
    create_line_plot_for_all_configs(valid_configs, config_map, target_dir)
    
    # 创建单独的折线图
    print("\n创建单独折线图...")
    create_individual_line_plots(valid_configs, config_map, target_dir)
    
    # 创建按节点数分组的比较图
    print("\n创建节点数比较图...")
    create_comparison_by_node_count(valid_configs, target_dir)
    
    # 生成汇总报告
    create_summary_report(all_config_data, target_dir)
    
    print(f"\n分析完成！结果已保存到: {target_dir}")


if __name__ == "__main__":
    # 配置参数
    BASE_DIR = r"F:\PostGraduate\Point-to-Point-DATA\deal-data-code\C-lop-Prediction\analysis_data\analysis_for_all_type_data\1-16nodes-data"
    TARGET_DIR = r"F:\PostGraduate\Point-to-Point-DATA\deal-data-code\C-lop-Prediction\analysis_for_non_block\plots_for_all_configs"
    EXCEL_PATH = r"F:\PostGraduate\Point-to-Point-DATA\deal-data-code\C-lop-Prediction\static\dataset.xlsx"
    
    # 检查路径是否存在
    if not os.path.exists(BASE_DIR):
        print(f"错误: 基础目录不存在 - {BASE_DIR}")
        exit(1)
    
    if not os.path.exists(EXCEL_PATH):
        print(f"错误: Excel文件不存在 - {EXCEL_PATH}")
        exit(1)
    
    # 运行主函数
    main(BASE_DIR, TARGET_DIR, EXCEL_PATH)